package com.inmaytide.website.utils.security;

import com.inmaytide.website.domain.entities.system.SysPermission;
import com.inmaytide.website.domain.entities.system.SysUser;
import com.inmaytide.website.service.system.SysPermissionService;
import com.inmaytide.website.service.system.SysRoleService;
import com.inmaytide.website.service.system.SysUserService;
import com.inmaytide.website.utils.CommonUtils;
import com.inmaytide.website.utils.configurations.SystemConstants;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * @author luomiao
 * @since May 15, 2016
 */
@Component
public class ShiroRealm extends AuthorizingRealm {

    @Resource
    private SysUserService userService;

    @Resource
    private SysRoleService roleService;

    @Resource
    private SysPermissionService permissionService;

    public ShiroRealm() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
        setCredentialsMatcher(matcher);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Objects.requireNonNull(principals, "PrincipalCollection method argument cannot be null.");
        String username = (String) getAvailablePrincipal(principals);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        SysUser user = userService.get(username);
        info.addRoles(roleService.findUserRoleCodes(user.getId()));
        List<SysPermission> permissions = permissionService.findPermissionsByRoleCodes(info.getRoles());
        info.addStringPermissions(permissionService.findPermissionCodesByPermissions(permissions));
        CommonUtils.setSessionAttribute(SystemConstants.SESSION_CURRENTUSER_PERMISSIONS_KEY, permissions);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        Objects.requireNonNull(token, "parameter token is null");
        String username = ((UsernamePasswordToken) token).getUsername();
        SysUser user = userService.get(username);
        if (ObjectUtils.isEmpty(user)) {    //用户不存在
            throw new UnknownAccountException("UnknownAccount: " + username);
        }
        if (user.isLock()) {   //用户被锁定
            throw new LockedAccountException("LockedAccount: " + username);
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo();
        info.setPrincipals(new SimplePrincipalCollection(username, getName()));
        info.setCredentials(user.getLoginPassword());
        CommonUtils.setSessionAttribute(SystemConstants.SESSION_CURRENTUSER_KEY, user);
        return info;
    }
}
